home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
359_11
/
patch5.000
/
GO32_SYMS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-11
|
15KB
|
692 lines
/* This is file SYMS.C */
/*
** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* History:250,1 */
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <io.h>
#include "build.h"
#include "types.h"
#include "syms.h"
#include "tss.h"
#include "stab.h"
#include "aout.h"
#include "utils.h"
#if DEBUGGER
#define SYMADDR 0xa0000000
static word32 sym_brk=SYMADDR;
word32 salloc(word32 size)
{
word32 r = sym_brk;
size = (size+3)&~3;
sym_brk +=size;
return r;
}
symsput(word32 where, void *ptr, int size)
{
memput(where, ptr, size);
}
symsget(word32 where, void *ptr, int size)
{
memget(where, ptr, size);
}
typedef struct SYMTREE {
word32 me;
word32 nleft, nright, ndown;
word32 vleft, vright, vdown;
word32 val;
word32 type;
word32 name_len;
} SYMTREE;
typedef struct FILENODE {
word32 me;
word32 next;
word32 line_list;
word32 first_addr, last_addr;
word32 name_len;
} FILENODE;
typedef struct LINENODE {
word32 me;
word32 next;
word32 num;
word32 addr;
} LINENODE;
static word32 symtree_root=0;
static word32 file_list=0;
static word32 nsyms=0;
static char tmps[256];
static char tmps2[256];
static word32 symtree_add(word32 val, word32 type, char *name)
{
SYMTREE s, sv, temp;
int cval;
int32 cval32;
memset(&temp, 0, sizeof(temp));
temp.name_len = strlen(name) + 1;
temp.me = salloc(sizeof(temp)+temp.name_len);
temp.val = val;
temp.type = type;
symsput(temp.me, &temp, sizeof(temp));
symsput(temp.me+sizeof(temp), name, temp.name_len);
if (symtree_root == 0)
{
symtree_root = temp.me;
return temp.me;
}
s.me = symtree_root;
while (1)
{
symsget(s.me, &s, sizeof(s));
symsget(s.me+sizeof(s), tmps, s.name_len);
cval = strcmp(name, tmps);
if ((cval == 0) &&
( (s.val == 0)
|| (val == 0)
|| (s.val == val)))
{
if (val)
{
s.val = val;
s.type = type;
symsput(s.me, &s, sizeof(s));
}
return temp.me;
}
else if (cval == 0)
{
if (s.ndown == 0)
{
s.ndown = temp.me;
symsput(s.me, &s, sizeof(s));
break;
}
s.me = s.ndown;
}
else if (cval < 0)
{
if (s.nleft == 0)
{
s.nleft = temp.me;
symsput(s.me, &s, sizeof(s));
break;
}
s.me = s.nleft;
}
else
{
if (s.nright == 0)
{
s.nright = temp.me;
symsput(s.me, &s, sizeof(s));
break;
}
s.me = s.nright;
}
}
nsyms++;
sv.me = symtree_root;
while (1)
{
symsget(sv.me, &sv, sizeof(sv));
if (sv.me == temp.me)
return temp.me;
cval32 = val - sv.val;
if (cval32 == 0)
{
if (sv.vdown == 0)
{
sv.vdown = temp.me;
symsput(sv.me, &sv, sizeof(sv));
break;
}
sv.me = sv.vdown;
}
else if (cval32 < 0)
{
if (sv.vleft == 0)
{
sv.vleft = temp.me;
symsput(sv.me, &sv, sizeof(sv));
break;
}
sv.me = sv.vleft;
}
else
{
if (sv.vright == 0)
{
sv.vright = temp.me;
symsput(sv.me, &sv, sizeof(sv));
break;
}
sv.me = sv.vright;
}
}
return temp.me;
}
static symtree_print(word32 s, int byval, int level)
{
SYMTREE tmp;
if (s == 0)
return;
symsget(s, &tmp, sizeof(tmp));
if (byval)
symtree_print(tmp.vleft, byval, level+1);
else
symtree_print(tmp.nleft, byval, level+1);
symsget(tmp.me+sizeof(tmp), tmps, tmp.name_len);
printf("0x%08lx 0x%08lx %*s%s\n", tmp.val, tmp.type, level, "", tmps);
if (byval)
symtree_print(tmp.vdown, byval, level);
else
symtree_print(tmp.ndown, byval, level);
if (byval)
symtree_print(tmp.vright, byval, level+1);
else
symtree_print(tmp.nright, byval, level+1);
}
void syms_list(v)
{
symtree_print(symtree_root, v, 0);
}
typedef struct SYM_ENTRY {
word32 string_off;
word8 type;
word8 other;
word16 desc;
word32 val;
} SYM_ENTRY;
get_string(FILE *f, word32 where)
{
char *cp;
if (where != ftell(f))
fseek(f, where, 0);
cp = tmps2;
do {
*cp++ = fgetc(f);
} while (cp[-1]);
}
void syms_init(char *fname)
{
GNU_AOUT header;
int fd, j, per, oldper=-1;
word32 nsyms, i;
FILE *sfd;
word32 sfd_base;
SYM_ENTRY sym;
char *strings, *cp;
word32 string_size;
word32 last_dot_o=0;
FILENODE filen;
LINENODE linen;
filen.me = 0;
linen.me = 0;
fd = open(fname, O_RDONLY | O_BINARY);
sfd = fopen(fname, "rb");
read(fd, &header, sizeof(header));
if ((header.info & 0xffff) == 0x14c)
{
lseek(fd, 0xa8L, 0);
read(fd, &header, sizeof(header));
lseek(fd, 0xa8+sizeof(header) + header.tsize + header.dsize, 0);
}
else if (((header.info & 0xffff) == 0x10b) ||
((header.info & 0xffff) == 0x0107))
{
lseek(fd, sizeof(header) + header.tsize + header.dsize
+ header.txrel + header.dtrel, 0);
}
else
{
nsyms = 0;
return;
}
printf("Reading symbols... 0%%");
fflush(stdout);
nsyms = header.symsize / sizeof(SYM_ENTRY);
fseek(sfd, tell(fd)+header.symsize, 0);
sfd_base = ftell(sfd);
for (i=0; i<nsyms; i++)
{
if (nsyms > 1)
per = i*100L/(nsyms-1);
else
per = 100;
if (per != oldper)
{
printf("\b\b\b\b%3d%%", per);
fflush(stdout);
oldper = per;
}
read(fd, &sym, sizeof(sym));
if (sym.string_off)
get_string(sfd, sfd_base+sym.string_off);
switch (sym.type)
{
case N_TEXT:
case N_TEXT | N_EXT:
cp = tmps2;
cp += strlen(cp) - 2;
if (strcmp(cp, ".o") == 0)
{
last_dot_o = sym.val;
if (filen.me && (filen.last_addr == 0))
{
filen.last_addr = last_dot_o - 1;
symsput(filen.me, &filen, sizeof(filen));
}
break;
}
if (strcmp(cp, "d.") == 0) /* as in gcc_compiled. */
break;
case N_DATA:
case N_DATA | N_EXT:
case N_ABS:
case N_ABS | N_EXT:
case N_BSS:
case N_BSS | N_EXT:
case N_FN:
case N_SETV:
case N_SETV | N_EXT:
case N_SETA:
case N_SETA | N_EXT:
case N_SETT:
case N_SETT | N_EXT:
case N_SETD:
case N_SETD | N_EXT:
case N_SETB:
case N_SETB | N_EXT:
case N_INDR:
case N_INDR | N_EXT:
if (sym.string_off)
symtree_add(sym.val, sym.type, tmps2);
break;
case N_SO:
memset(&filen, 0, sizeof(FILENODE));
filen.name_len = strlen(tmps2)+1;
filen.me = salloc(sizeof(FILENODE)+filen.name_len);
symsput(filen.me+sizeof(filen), tmps2, filen.name_len);
filen.next = file_list;
file_list = filen.me;
filen.first_addr = last_dot_o;
symsput(filen.me, &filen, sizeof(filen));
break;
case N_SLINE:
memset(&linen, 0, sizeof(linen));
linen.me = salloc(sizeof(LINENODE));
linen.next = filen.line_list;
filen.line_list = linen.me;
linen.num = sym.desc;
linen.addr = sym.val;
symsput(linen.me, &linen, sizeof(linen));
symsput(filen.me, &filen, sizeof(filen));
break;
}
}
printf(" %ld s